package me.flyray.bsin.server.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import com.plexpt.chatgpt.entity.billing.Usage;
import com.plexpt.chatgpt.entity.chat.ChatCompletionResponse;
import me.flyray.bsin.cache.BsinCacheProvider;
import me.flyray.bsin.constants.ResponseCode;
import me.flyray.bsin.exception.BusinessException;
import me.flyray.bsin.facade.service.OpenAiService;
import me.flyray.bsin.server.config.ChatGPTConfiguration;
import me.flyray.bsin.server.domain.AiModel;
import me.flyray.bsin.server.domain.TenantWxPlatform;
import me.flyray.bsin.server.domain.TenantWxPlatformRole;
import me.flyray.bsin.server.mapper.AiModelMapper;
import me.flyray.bsin.server.mapper.AiTenantWxPlatformMapper;
import me.flyray.bsin.server.mapper.AiTenantWxPlatformRoleMapper;
import me.flyray.bsin.server.utils.OpenAI;
import me.flyray.bsin.utils.RespBodyHandler;
import me.flyray.bsin.wordFilter.SensitiveWordFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author leonard
 * @description Bsin-PaaS openAI Service实现
 * @createDate 2023-04-28 18:41:30
 */
@Service
public class OpenAiServiceImpl implements OpenAiService {

    @Autowired
    private OpenAI openAI;
    @Autowired
    private AiModelMapper aiModelMapper;
    @Autowired
    private AiTenantWxPlatformMapper tenantWxmpMapper;
    @Autowired
    private AiTenantWxPlatformRoleMapper tenantWxmpRoleMapper;
    @Autowired
    private BsinCacheProvider bsinCacheProvider;
    private static long last_time = 0;
    private static long current_time = 0;
    @Autowired
    private SensitiveWordFilter sensitiveWordFilter;

    @Value("${bsin.ai.aesKey}")
    private String aesKey;
    @Value("${bsin.ai.sensitiveWordPath}")
    private String sensitiveWordPath;

    /**
     * 对话连天：基于上下文的对话连天
     */
    @Override
    public Map<String, Object> chatCompletion(Map<String, Object> requestMap) {
        ChatCompletionResponse chatCompletionResponse = null;
        try {
            String tenantId = (String) requestMap.get("tenantId");
            String key = (String) requestMap.get("openAiKey");
            String url = (String) requestMap.get("openAiUrl");
            String userContent = (String) requestMap.get("userContent");
            String systemContent = (String) requestMap.get("systemContent");
            Integer contextLimitNum = new Integer((String) requestMap.get("contextLimitNum"));
            String model = (String) requestMap.get("model");
            String temperature = (String) requestMap.get("temperature");
            Boolean contextEnable = Boolean.valueOf((String) requestMap.get("contextEnable"));
            Boolean proxyEnabled = Boolean.valueOf((String) requestMap.get("proxyEnabled"));
            Integer maxToken = new Integer((String) requestMap.get("maxToken"));
            Integer contestExpire = new Integer((String) requestMap.get("contestExpire"));
            ChatGPTConfiguration chatGPTConfiguration = new ChatGPTConfiguration();
            chatGPTConfiguration.setSystemContent(systemContent);
            chatGPTConfiguration.setKey(key);
            List<String> keyList = new ArrayList<String>();
            keyList.add(key);
            chatGPTConfiguration.setKeyList(keyList);
            chatGPTConfiguration.setContextEnable(contextEnable);
            chatGPTConfiguration.setProxyEnable(proxyEnabled);
            chatGPTConfiguration.setMaxToken(maxToken);
            chatGPTConfiguration.setModel(model);
            chatGPTConfiguration.setUserId(tenantId);
            chatGPTConfiguration.setUserContent(userContent);
            chatGPTConfiguration.setContextLimitNum(contextLimitNum);
            chatGPTConfiguration.setTemperature(Double.parseDouble(temperature));
            chatGPTConfiguration.setUrl(url);
            chatGPTConfiguration.setContextExpire(contestExpire.longValue());
            chatCompletionResponse = openAI.chatCompletion(chatGPTConfiguration);
        } catch (Exception e) {
            throw new BusinessException(ResponseCode.FAIL);
        }
        return RespBodyHandler.setRespBodyDto(chatCompletionResponse);
    }


    /**
     * 对话连天：微信平台基于上下文的对话连天
     */
    @Override
    public Map<String, Object> wxChatCompletion(Map<String, Object> requestMap) {
        ChatCompletionResponse chatCompletionResponse = null;
        try {
            String tenantId = (String) requestMap.get("tenantId");
            String userContent = (String) requestMap.get("userContent");
            TenantWxPlatform tenantWxPlatform = tenantWxmpMapper.selectByAppId(tenantId);
            SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, aesKey.getBytes());
            // 获取公众号配置的对应AI模型
            AiModel aiModel = aiModelMapper.selectBySerialNo(tenantWxPlatform.getAiModelNo());
            ChatGPTConfiguration chatGPTConfiguration = BeanUtil.copyProperties(aiModel, ChatGPTConfiguration.class);
            String openaiKey = aes.decryptStr(aiModel.getKey(), CharsetUtil.CHARSET_UTF_8);
            chatGPTConfiguration.setKey(openaiKey);
            List<String> openaiKeyList = Arrays.asList(openaiKey);
            chatGPTConfiguration.setKeyList(openaiKeyList);
            chatGPTConfiguration.setUserId(tenantId);
            //AI模型的system role
            TenantWxPlatformRole tenantWxmpRole = tenantWxmpRoleMapper.selectByTenantId(tenantWxPlatform.getTenantId());
            chatGPTConfiguration.setSystemContent(tenantWxmpRole.getContent());
            chatGPTConfiguration.setUserContent(userContent);
            // 非超时请求才做回复：limit时间
            current_time = System.currentTimeMillis();
            String preResponse = chatGPTConfiguration.getPreResponse();

            //敏感词过滤
            if (sensitiveWordFilter.wordList == null) {
                sensitiveWordFilter.loadWordFromFile(sensitiveWordPath);
            }
            Map<String, Object> ret = sensitiveWordFilter.Filter(userContent);
            if ((boolean) ret.get("isContain")) {
                throw new BusinessException("999999", "请求包含敏感词");
            } else if (current_time - last_time > 5000) {
                chatCompletionResponse = openAI.chatCompletion(chatGPTConfiguration);
                Usage usage = chatCompletionResponse.getUsage();
                last_time = current_time;
            } else {
                System.out.println("**************调用过于频繁或者是触发微信公众号retry机制****************");
                throw new BusinessException("999999", "调用过于频繁");
            }
        } catch (Exception e) {
            System.out.println("******************************" + e.toString());
            throw new BusinessException("999999", e.toString());
        }
        return RespBodyHandler.setRespBodyDto(chatCompletionResponse);
    }

    /**
     * 信用卡余额查询
     */
    @Override
    public Map<String, Object> creditGrants(Map<String, Object> requestMap) {

        return null;
    }

}
